﻿// 2025/10/13: 首个版本
// 2025/10/17: 选项排序

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Avalonia.Input;
using Avalonia.Media;
using ASEva;
using ASEva.UIAvalonia;
using ASEva.Utility;

namespace CommonSource
{
    partial class BusMessageAdder : DialogPanel
    {
        public BusMessageAdder() // For designer
        {
            InitializeComponent();
            language = new LanguageSwitch(Resources, AgencyLocal.GetAppLanguage());
        }

        public BusMessageAdder(List<String> addedBusMessageIDs, SelectBusMessageHandler handler, String iconResourceName = null)
        {
            InitializeComponent();
            SetResizableMode(300, 300, 440, 570);
            language = new LanguageSwitch(Resources, AgencyLocal.GetAppLanguage());
            Icon = ResourceLoader.Load(iconResourceName)?.ToAvaloniaWindowIcon();
            Title = language["title"];
            model = new BusMessageAdderVideModel(language, addedBusMessageIDs == null ? [] : addedBusMessageIDs.ToArray().ToList(), handler);
            DataContext = model;
            initializeTree();
        }

        private async void initializeTree()
        {
            model.Initialize(await AgencyAsync.GetSignalTree());
        }

        private void TreeViewItem_PointerPressed(object sender, PointerPressedEventArgs e)
        {
            if (e.ClickCount == 2) model.Add();
        }

        private LanguageSwitch language;
        private BusMessageAdderVideModel model;
    }

    partial class BusMessageAdderVideModel(LanguageSwitch language, List<String> addedBusMessageIDs, SelectBusMessageHandler handler) : ObservableObject
    {
        public enum TextColor
        {
            Default = 0,
            Green,
            Blue,
            Gray,
        }

        public partial class Node(String key, String _title, bool canBeTarget) : ObservableObject
        {
            public String Key { get; set; } = key;
            public bool CanBeTarget { get; set; } = canBeTarget;

            [ObservableProperty]
            private String title = _title;

            [ObservableProperty]
            [NotifyPropertyChangedFor(nameof(Foreground))]
            private TextColor textColor = TextColor.Default;

            public IBrush Foreground => TextColor switch
            {
                TextColor.Green => App.DarkTheme ? Brushes.PaleGreen : Brushes.DarkGreen,
                TextColor.Blue => App.DarkTheme ? Brushes.SkyBlue : Brushes.DarkBlue,
                TextColor.Gray => Brushes.Gray,
                _ => App.DarkTheme ? Brushes.LightGray : Brushes.Black,
            };

            [ObservableProperty]
            private bool isExpanded = false;

            [ObservableProperty]
            private ObservableCollection<Node> subNodes = new();
        }

        [ObservableProperty]
        private bool canSearch = false;

        [ObservableProperty]
        private String searchText = "";

        [ObservableProperty]
        private ObservableCollection<Node> treeNodes = new();

        [ObservableProperty]
        [NotifyPropertyChangedFor(nameof(CanAdd))]
        private Node selectedTreeNode = null;

        [ObservableProperty]
        [NotifyPropertyChangedFor(nameof(CanAdd))]
        private bool addButtonDisabled = false;

        public bool CanAdd => SelectedTreeNode != null && SelectedTreeNode.CanBeTarget && !addedBusMessageIDs.Contains(SelectedTreeNode.Key) && !AddButtonDisabled;

        [RelayCommand]
        public void Add()
        {
            if (!CanAdd) return;
            var busMessageID = SelectedTreeNode.Key;
            if (!handler.SelectBusMessage(busMessageID)) AddButtonDisabled = true;
            addedBusMessageIDs.Add(busMessageID);
            SelectedTreeNode.TextColor = TextColor.Green;
            SelectedTreeNode = null;
        }

        public void Initialize(SignalTreeNode[] fullTree)
        {
            this.fullTree = fullTree;
            if (fullTree != null && updateTreeNodes()) CanSearch = true;
            else addNoAvailable();
        }

        partial void OnSearchTextChanged(string value)
        {
            if (!updateTreeNodes()) addNoAvailable();
        }

        private bool updateTreeNodes()
        {
            var topNodes = new List<Node>();
            var itemAdded = false;
            var key = SearchText?.ToLower() ?? "";
            bool keyValid = key.Length >= 2;

            foreach (var top in fullTree)
            {
                if (top.Type != SignalTreeNodeType.BusProtocol) continue;

                var topMatch = keyValid && top.Name.ToLower().Contains(key);

                var topNode = new Node(top.ID, top.Name, false);
                var shouldAddTopNode = !keyValid || topMatch;

                var middleNodes = new List<Node>();
                foreach (var middle in top.Children)
                {
                    var middleMatch = keyValid && (middle.ID.ToLower().Contains(key) || middle.Name.ToLower().Contains(key));
                    var isAdded = (int)middle.Type == (int)SignalTreeNodeType.BusMessage && addedBusMessageIDs.Contains(middle.ID);

                    var middleNode = new Node(middle.ID, middle.Name, true) { TextColor = isAdded ? TextColor.Green : TextColor.Blue };
                    bool shouldAddMiddleNode = !keyValid || topMatch || middleMatch;

                    if (shouldAddMiddleNode)
                    {
                        middleNodes.Add(middleNode);
                        shouldAddTopNode = true;
                    }
                }

                if (shouldAddTopNode)
                {
                    foreach (var middleNode in middleNodes.OrderBy(node => node.Title))
                    {
                        topNode.SubNodes.Add(middleNode);
                    }
                    if (keyValid) topNode.IsExpanded = true;
                    topNodes.Add(topNode);
                    itemAdded = true;
                }
            }

            TreeNodes.Clear();
            foreach (var topNode in topNodes.OrderBy(node => node.Title))
            {
                TreeNodes.Add(topNode);
            }

            return itemAdded;
        }

        private void addNoAvailable()
        {
            TreeNodes.Clear();
            TreeNodes.Add(new Node(null, language["no-available"], false){ TextColor = TextColor.Gray });
        }

        private SignalTreeNode[] fullTree;
    }
}